<template>
  <!-- 遮罩层 -->
  <Teleport to="body">
    <Transition name="modal-backdrop" appear>
      <div
        v-if="visible"
        class="modal-backdrop"
        :class="backdropClass"
        @click="handleBackdropClick"
      >
        <!-- 模态框容器 -->
        <Transition name="modal" appear>
          <div
            v-if="visible"
            ref="modalRef"
            class="modal"
            :class="modalClass"
            :style="modalStyle"
            @click.stop
            role="dialog"
            :aria-modal="true"
            :aria-labelledby="titleId"
            :aria-describedby="contentId"
          >
            <!-- 模态框头部 -->
            <div v-if="showHeader" class="modal-header" :class="headerClass">
              <div class="modal-title-wrapper">
                <!-- 图标 -->
                <Icon
                  v-if="icon"
                  :name="icon"
                  :size="iconSize"
                  class="modal-icon"
                  :class="`modal-icon-${type}`"
                />

                <!-- 标题 -->
                <h3
                  v-if="title || $slots.title"
                  :id="titleId"
                  class="modal-title"
                >
                  <slot name="title">{{ title }}</slot>
                </h3>
              </div>

              <!-- 头部操作按钮 -->
              <div class="modal-header-actions">
                <slot name="header-actions"></slot>

                <!-- 关闭按钮 -->
                <button
                  v-if="closable"
                  class="modal-close"
                  @click="handleClose"
                  :title="closeText"
                >
                  <Icon name="x" :size="16" />
                </button>
              </div>
            </div>

            <!-- 模态框内容 -->
            <div :id="contentId" class="modal-content" :class="contentClass">
              <slot></slot>
            </div>

            <!-- 模态框底部 -->
            <div v-if="showFooter" class="modal-footer" :class="footerClass">
              <slot name="footer">
                <!-- 默认按钮 -->
                <div class="modal-footer-actions">
                  <Button
                    v-if="showCancelButton"
                    :type="cancelButtonType"
                    :variant="cancelButtonVariant"
                    :size="buttonSize"
                    :disabled="loading"
                    @click="handleCancel"
                  >
                    {{ cancelText }}
                  </Button>

                  <Button
                    v-if="showConfirmButton"
                    :type="confirmButtonType"
                    :variant="confirmButtonVariant"
                    :size="buttonSize"
                    :loading="loading"
                    @click="handleConfirm"
                  >
                    {{ confirmText }}
                  </Button>
                </div>
              </slot>
            </div>

            <!-- 调整大小手柄 -->
            <div
              v-if="resizable"
              class="modal-resize-handle"
              @mousedown="handleResizeStart"
            ></div>
          </div>
        </Transition>
      </div>
    </Transition>
  </Teleport>
</template>

<script setup lang="ts">
import { ref, computed, watch, nextTick, onMounted, onUnmounted } from "vue";
import { generateId } from "@/utils";
import Icon from "./Icon.vue";
import Button from "./Button.vue";

interface Props {
  // 显示控制
  visible?: boolean;

  // 基础属性
  title?: string;
  width?: string | number;
  height?: string | number;
  maxWidth?: string | number;
  maxHeight?: string | number;
  minWidth?: string | number;
  minHeight?: string | number;

  // 样式
  size?: "mini" | "small" | "medium" | "large" | "fullscreen";
  type?: "default" | "info" | "success" | "warning" | "error";
  centered?: boolean;

  // 功能
  closable?: boolean;
  maskClosable?: boolean;
  keyboard?: boolean;
  draggable?: boolean;
  resizable?: boolean;

  // 头部和底部
  showHeader?: boolean;
  showFooter?: boolean;

  // 按钮配置
  showCancelButton?: boolean;
  showConfirmButton?: boolean;
  cancelText?: string;
  confirmText?: string;
  cancelButtonType?: string;
  confirmButtonType?: string;
  cancelButtonVariant?: string;
  confirmButtonVariant?: string;
  buttonSize?: string;

  // 状态
  loading?: boolean;

  // 其他
  icon?: string;
  closeText?: string;
  zIndex?: number;

  // 类名
  backdropClass?: string;
  modalClass?: string;
  headerClass?: string;
  contentClass?: string;
  footerClass?: string;
}

const props = withDefaults(defineProps<Props>(), {
  size: "medium",
  type: "default",
  closable: true,
  maskClosable: true,
  keyboard: true,
  showHeader: true,
  showFooter: true,
  showCancelButton: true,
  showConfirmButton: true,
  cancelText: "取消",
  confirmText: "确定",
  cancelButtonType: "secondary",
  confirmButtonType: "primary",
  cancelButtonVariant: "outlined",
  confirmButtonVariant: "filled",
  buttonSize: "medium",
  closeText: "关闭",
  zIndex: 1000,
});

const emit = defineEmits<{
  "update:visible": [visible: boolean];
  open: [];
  close: [];
  confirm: [];
  cancel: [];
  afterOpen: [];
  afterClose: [];
}>();

// 响应式数据
const modalRef = ref<HTMLElement>();
const isDragging = ref(false);
const isResizing = ref(false);
const dragOffset = ref({ x: 0, y: 0 });
const modalPosition = ref({ x: 0, y: 0 });
const modalSize = ref({ width: 0, height: 0 });

// 计算属性
const titleId = computed(() => generateId("modal-title"));
const contentId = computed(() => generateId("modal-content"));

const iconSize = computed(() => {
  const sizeMap = {
    mini: 16,
    small: 18,
    medium: 20,
    large: 22,
    fullscreen: 24,
  };
  return sizeMap[props.size];
});

const modalStyle = computed(() => {
  const styles: Record<string, string> = {};

  // 尺寸
  if (props.width) {
    styles.width =
      typeof props.width === "number" ? `${props.width}px` : props.width;
  }
  if (props.height) {
    styles.height =
      typeof props.height === "number" ? `${props.height}px` : props.height;
  }
  if (props.maxWidth) {
    styles.maxWidth =
      typeof props.maxWidth === "number"
        ? `${props.maxWidth}px`
        : props.maxWidth;
  }
  if (props.maxHeight) {
    styles.maxHeight =
      typeof props.maxHeight === "number"
        ? `${props.maxHeight}px`
        : props.maxHeight;
  }
  if (props.minWidth) {
    styles.minWidth =
      typeof props.minWidth === "number"
        ? `${props.minWidth}px`
        : props.minWidth;
  }
  if (props.minHeight) {
    styles.minHeight =
      typeof props.minHeight === "number"
        ? `${props.minHeight}px`
        : props.minHeight;
  }

  // 位置（拖拽后）
  if (modalPosition.value.x !== 0 || modalPosition.value.y !== 0) {
    styles.transform = `translate(${modalPosition.value.x}px, ${modalPosition.value.y}px)`;
  }

  // 动态尺寸（调整大小后）
  if (modalSize.value.width > 0) {
    styles.width = `${modalSize.value.width}px`;
  }
  if (modalSize.value.height > 0) {
    styles.height = `${modalSize.value.height}px`;
  }

  // z-index
  if (props.zIndex) {
    styles.zIndex = props.zIndex.toString();
  }

  return styles;
});

// 事件处理
const handleClose = () => {
  emit("update:visible", false);
  emit("close");
};

const handleConfirm = () => {
  emit("confirm");
};

const handleCancel = () => {
  emit("cancel");
  if (!props.loading) {
    handleClose();
  }
};

const handleBackdropClick = () => {
  if (props.maskClosable && !props.loading) {
    handleClose();
  }
};

// 键盘事件
const handleKeydown = (event: KeyboardEvent) => {
  if (!props.visible || !props.keyboard) return;

  if (event.key === "Escape") {
    event.preventDefault();
    handleClose();
  }
};

// 拖拽功能
const handleDragStart = (event: MouseEvent) => {
  if (!props.draggable || isResizing.value) return;

  isDragging.value = true;
  const rect = modalRef.value?.getBoundingClientRect();
  if (rect) {
    dragOffset.value = {
      x: event.clientX - rect.left,
      y: event.clientY - rect.top,
    };
  }

  document.addEventListener("mousemove", handleDragMove);
  document.addEventListener("mouseup", handleDragEnd);
  event.preventDefault();
};

const handleDragMove = (event: MouseEvent) => {
  if (!isDragging.value) return;

  const x = event.clientX - dragOffset.value.x - window.innerWidth / 2;
  const y = event.clientY - dragOffset.value.y - window.innerHeight / 2;

  modalPosition.value = { x, y };
};

const handleDragEnd = () => {
  isDragging.value = false;
  document.removeEventListener("mousemove", handleDragMove);
  document.removeEventListener("mouseup", handleDragEnd);
};

// 调整大小功能
const handleResizeStart = (event: MouseEvent) => {
  if (!props.resizable) return;

  isResizing.value = true;
  const rect = modalRef.value?.getBoundingClientRect();
  if (rect) {
    modalSize.value = {
      width: rect.width,
      height: rect.height,
    };
  }

  const startX = event.clientX;
  const startY = event.clientY;
  const startWidth = modalSize.value.width;
  const startHeight = modalSize.value.height;

  const handleResizeMove = (e: MouseEvent) => {
    const deltaX = e.clientX - startX;
    const deltaY = e.clientY - startY;

    modalSize.value = {
      width: Math.max(200, startWidth + deltaX),
      height: Math.max(150, startHeight + deltaY),
    };
  };

  const handleResizeEnd = () => {
    isResizing.value = false;
    document.removeEventListener("mousemove", handleResizeMove);
    document.removeEventListener("mouseup", handleResizeEnd);
  };

  document.addEventListener("mousemove", handleResizeMove);
  document.addEventListener("mouseup", handleResizeEnd);
  event.preventDefault();
};

// 监听显示状态变化
watch(
  () => props.visible,
  (newVisible) => {
    if (newVisible) {
      emit("open");
      nextTick(() => {
        emit("afterOpen");
        // 聚焦到模态框
        modalRef.value?.focus();
      });
    } else {
      emit("afterClose");
      // 重置位置和大小
      modalPosition.value = { x: 0, y: 0 };
      modalSize.value = { width: 0, height: 0 };
    }
  },
);

// 生命周期
onMounted(() => {
  document.addEventListener("keydown", handleKeydown);

  // 添加拖拽事件监听
  if (props.draggable) {
    const header = modalRef.value?.querySelector(".modal-header");
    if (header) {
      header.addEventListener("mousedown", handleDragStart);
    }
  }
});

onUnmounted(() => {
  document.removeEventListener("keydown", handleKeydown);
  document.removeEventListener("mousemove", handleDragMove);
  document.removeEventListener("mouseup", handleDragEnd);
});

// 公开方法
const close = () => {
  handleClose();
};

const confirm = () => {
  handleConfirm();
};

const cancel = () => {
  handleCancel();
};

defineExpose({
  close,
  confirm,
  cancel,
  modalRef,
});
</script>

<style scoped>
/* 遮罩层 */
.modal-backdrop {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 20px;
}

.modal-backdrop.centered {
  align-items: center;
}

/* 模态框 */
.modal {
  background-color: var(--bg-color);
  border-radius: 12px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2);
  display: flex;
  flex-direction: column;
  max-width: 90vw;
  max-height: 90vh;
  position: relative;
  outline: none;
  overflow: hidden;
}

/* 尺寸 */
.modal.modal-mini {
  width: 300px;
}

.modal.modal-small {
  width: 400px;
}

.modal.modal-medium {
  width: 600px;
}

.modal.modal-large {
  width: 800px;
}

.modal.modal-fullscreen {
  width: 100vw;
  height: 100vh;
  max-width: 100vw;
  max-height: 100vh;
  border-radius: 0;
}

/* 类型样式 */
.modal.modal-info .modal-icon {
  color: var(--info-color);
}

.modal.modal-success .modal-icon {
  color: var(--success-color);
}

.modal.modal-warning .modal-icon {
  color: var(--warning-color);
}

.modal.modal-error .modal-icon {
  color: var(--error-color);
}

/* 头部 */
.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 24px;
  border-bottom: 1px solid var(--border-color);
  cursor: move;
}

.modal-title-wrapper {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: 1;
  min-width: 0;
}

.modal-title {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.modal-icon {
  flex-shrink: 0;
}

.modal-header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

.modal-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: none;
  background: none;
  border-radius: 6px;
  cursor: pointer;
  color: var(--text-tertiary);
  transition: all 0.2s ease;
}

.modal-close:hover {
  background-color: var(--hover-bg);
  color: var(--text-primary);
}

/* 内容 */
.modal-content {
  flex: 1;
  padding: 24px;
  overflow-y: auto;
  color: var(--text-primary);
  line-height: 1.6;
}

.modal-content::-webkit-scrollbar {
  width: 6px;
}

.modal-content::-webkit-scrollbar-track {
  background: var(--bg-secondary);
}

.modal-content::-webkit-scrollbar-thumb {
  background: var(--border-color);
  border-radius: 3px;
}

.modal-content::-webkit-scrollbar-thumb:hover {
  background: var(--border-color-hover);
}

/* 底部 */
.modal-footer {
  padding: 16px 24px 20px;
  border-top: 1px solid var(--border-color);
  background-color: var(--bg-secondary);
}

.modal-footer-actions {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

/* 调整大小手柄 */
.modal-resize-handle {
  position: absolute;
  bottom: 0;
  right: 0;
  width: 20px;
  height: 20px;
  cursor: se-resize;
  background: linear-gradient(
    -45deg,
    transparent 0%,
    transparent 40%,
    var(--border-color) 40%,
    var(--border-color) 60%,
    transparent 60%,
    transparent 100%
  );
}

.modal-resize-handle::before {
  content: "";
  position: absolute;
  bottom: 4px;
  right: 4px;
  width: 8px;
  height: 8px;
  background: linear-gradient(
    -45deg,
    transparent 0%,
    transparent 40%,
    var(--border-color) 40%,
    var(--border-color) 60%,
    transparent 60%,
    transparent 100%
  );
}

/* 动画 */
.modal-backdrop-enter-active,
.modal-backdrop-leave-active {
  transition: opacity 0.3s ease;
}

.modal-backdrop-enter-from,
.modal-backdrop-leave-to {
  opacity: 0;
}

.modal-enter-active {
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.modal-leave-active {
  transition: all 0.2s cubic-bezier(0.4, 0, 1, 1);
}

.modal-enter-from {
  opacity: 0;
  transform: scale(0.9) translateY(-20px);
}

.modal-leave-to {
  opacity: 0;
  transform: scale(0.95) translateY(-10px);
}

/* 拖拽状态 */
.modal.dragging {
  user-select: none;
  transition: none;
}

.modal.dragging .modal-header {
  cursor: grabbing;
}

/* 调整大小状态 */
.modal.resizing {
  user-select: none;
  transition: none;
}

/* 响应式 */
@media (max-width: 768px) {
  .modal-backdrop {
    padding: 10px;
  }

  .modal {
    width: 100% !important;
    max-width: 100%;
    margin: 0;
  }

  .modal-header {
    padding: 16px 20px;
    cursor: default;
  }

  .modal-content {
    padding: 20px;
  }

  .modal-footer {
    padding: 12px 20px 16px;
  }

  .modal-footer-actions {
    flex-direction: column-reverse;
    gap: 8px;
  }

  .modal-footer-actions .button {
    width: 100%;
  }

  .modal-title {
    font-size: 16px;
  }

  .modal-resize-handle {
    display: none;
  }
}

@media (max-width: 480px) {
  .modal-backdrop {
    padding: 0;
  }

  .modal {
    height: 100vh;
    max-height: 100vh;
    border-radius: 0;
  }
}

/* 暗色主题适配 */
@media (prefers-color-scheme: dark) {
  .modal-backdrop {
    background-color: rgba(0, 0, 0, 0.7);
  }

  .modal {
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4);
  }
}

/* 无障碍支持 */
@media (prefers-reduced-motion: reduce) {
  .modal-backdrop-enter-active,
  .modal-backdrop-leave-active,
  .modal-enter-active,
  .modal-leave-active {
    transition: none;
  }
}

/* 高对比度模式 */
@media (prefers-contrast: high) {
  .modal {
    border: 2px solid var(--text-primary);
  }

  .modal-header,
  .modal-footer {
    border-color: var(--text-primary);
  }
}
</style>
